package com.lap.auth.application.authorization.assembler;

import com.lap.auth.application.authorization.dto.ApiDto;
import com.lap.auth.application.authorization.dto.DataScopeDto;
import com.lap.auth.application.authorization.dto.MenuViewDto;
import com.lap.auth.application.role.dto.RoleDataScopeDto;
import com.lap.auth.domain.api.Api;
import com.lap.auth.domain.menu.Menu;
import com.lap.auth.shared.tools.BaseConverter;
import com.lap.framework.common.tool.BooleanStrategy;
import java.util.*;
import java.util.stream.Collectors;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

@Mapper(componentModel = "spring")
public interface AuthorAssembler extends BaseConverter {
  Integer ZERO = 0;
  Integer DEFAULT_RANK = 9999; // 添加默认排序值

  ApiDto toDto(Api api);

  List<ApiDto> toDtoList(List<Api> apiList);

  DataScopeDto toDataScopeDto(RoleDataScopeDto dto);

  @Mapping(target = "meta.title", source = "title")
  @Mapping(target = "meta.icon", source = "icon")
  @Mapping(target = "meta.extraIcon", source = "extraIcon")
  @Mapping(target = "meta.enterTransition", source = "enterTransition")
  @Mapping(target = "meta.leaveTransition", source = "leaveTransition")
  @Mapping(target = "meta.activePath", source = "activePath")
  @Mapping(target = "meta.frameSrc", source = "frameSrc")
  @Mapping(target = "meta.frameLoading", source = "frameLoading")
  @Mapping(target = "meta.showLink", source = "showLink")
  @Mapping(target = "meta.showParent", source = "showParent")
  @Mapping(target = "meta.keepAlive", source = "keepAlive")
  @Mapping(target = "meta.hiddenTag", source = "hiddenTag")
  @Mapping(target = "meta.fixedTag", source = "fixedTag")
  @Mapping(target = "meta.rank", source = "rank")
  @Mapping(target = "children", ignore = true)
  MenuViewDto toMenuDto(Menu menu);

  List<MenuViewDto> toMenuDtoList(List<Menu> list);

  default boolean intToBool(Integer value) {
    return BooleanStrategy.toBool(value);
  }

  /** 菜单树转换 */
  default List<MenuViewDto> convertToTree(List<MenuViewDto> allList) {
    if (allList == null || allList.isEmpty()) {
      return Collections.emptyList();
    }

    List<MenuViewDto> roots = new ArrayList<>();
    Map<Integer, MenuViewDto> nodeMap =
        allList.stream().collect(Collectors.toMap(MenuViewDto::getId, dto -> dto));

    for (MenuViewDto dto : allList) {
      if (dto.getParentId() == null || Objects.equals(dto.getParentId(), ZERO)) {
        roots.add(dto);
      } else {
        MenuViewDto parent = nodeMap.get(dto.getParentId());
        if (parent != null) {
          if (parent.getChildren() == null) {
            parent.setChildren(new ArrayList<>());
          }
          parent.getChildren().add(dto);
        }
      }
    }

    Comparator<MenuViewDto> safeComparator =
        Comparator.comparing(
            item ->
                (item.getMeta() != null && item.getMeta().getRank() != null)
                    ? item.getMeta().getRank()
                    : DEFAULT_RANK);

    for (MenuViewDto dto : nodeMap.values()) {
      if (dto.getChildren() != null && !dto.getChildren().isEmpty()) {
        dto.getChildren().sort(safeComparator);
      }
    }

    roots.sort(safeComparator);
    return roots;
  }
}
